package com.yanqu.road.server.manger.activity.entername;

import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.args.ValueFourParamArgs;
import com.yanqu.road.entity.activity.entername.ActivityGroupMatch;
import com.yanqu.road.entity.activity.entername.ChannelFightZone;
import com.yanqu.road.entity.activity.entername.EnterNameUtils;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.player.UserInfo;
import com.yanqu.road.pb.cross3.activity.EnterNameProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.entername.EnterNameActivityModule;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.entername.impl.AbstractEnterNameChangeListener;
import com.yanqu.road.server.manger.activity.entername.impl.DefaultEnterNameChannelListener;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.pb.PlayerPb;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class EnterNameActivityMgr extends TempMgr {

    private static Map<Integer, EnterNameActivityConfig> activityConfigMap = new ConcurrentHashMap<>();

    //activityId userId  报名缓存
    private static Map<Integer, Map<Long, EnterNameCache>> nameCacheMap = new ConcurrentHashMap<>();

    //activityId
    private static Map<Integer, List<ActivityGroupMatch>> matchMap = new ConcurrentHashMap<>();

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }

    public static void reloadActivityData() {

        //读取config

        // 在线玩家下发数据
        for (GamePlayer gamePlayer : GamePlayerMgr.getAllOnlinePlayer()) {
            EnterNameActivityModule module = gamePlayer.getModule(EnterNameActivityModule.class);
            module.syncConfig();
        }
    }

    /**
     * 分组消息通知，其他活动需要扩展
     */
    public static void notifyGrouping(int activityId, EnterNameProto.UserEnterNameMsg nameMsg, List<ActivityGroupMatch> groupMatches){
        List<AbstractEnterNameChangeListener> listeners = new ArrayList<>();
        listeners.add(new DefaultEnterNameChannelListener());
        //todo add
        if(groupMatches == null){
            groupMatches = new ArrayList<>();
        }
        for (AbstractEnterNameChangeListener listener : listeners) {
            listener.notifyGrouping(activityId, nameMsg, groupMatches);
        }
    }

    /**
     * 报名消息通知，其他活动需要扩展
     */
    public static void notifyName(int activityId, List<Long> userIdList){
        List<AbstractEnterNameChangeListener> listeners = new ArrayList<>();
        listeners.add(new DefaultEnterNameChannelListener());
        //todo add
        if(userIdList == null){
            userIdList = new ArrayList<>();
        }
        for (AbstractEnterNameChangeListener listener : listeners) {
            listener.notifyName(activityId, userIdList);
        }
    }

    public static boolean inEnterNameTime(int activityId){
        EnterNameActivityConfig activityConfig = getActivityConfig(activityId);
        if(activityConfig == null){
            return false;
        }
        long nowTime = System.currentTimeMillis() / 1000;
        return nowTime >= activityConfig.activityInfo.getBeginTime() && nowTime < activityConfig.getActivityInfo().getBeginTime() + activityConfig.getNameTime() * 60;
    }

    public static boolean inAutoEnterNameTime(int activityId){
        EnterNameActivityConfig activityConfig = getActivityConfig(activityId);
        if(activityConfig == null){
            return false;
        }
        long nowTime = System.currentTimeMillis() / 1000;
        long nameEndTime = activityConfig.getActivityInfo().getBeginTime() + 60 * activityConfig.getNameTime();
        long beginGroupingTime = activityConfig.getActivityInfo().getBeginTime() + 60 * activityConfig.getGroupTime();
        //有自动报名期，且不小于1分钟的自动报名期
        return nowTime >= nameEndTime && nameEndTime < beginGroupingTime && nowTime < nameEndTime + 60;
    }

    public static boolean activityInShowTime(int activityId){
        EnterNameActivityConfig activityConfig = getActivityConfig(activityId);
        if(activityConfig == null){
            return false;
        }
        return ActivityMgr.activityInShowTime(activityConfig.activityInfo);
    }

    public static EnterNameActivityConfig getActivityConfig(int activityId){
        return activityConfigMap.get(activityId);
    }

    /**
     * 其他活动需要扩展，初始活动时，设置一个配置
     */
    public static void putConfig(int activityId, EnterNameActivityConfig config){
        //移除已存在的
        ActivityInfo activityInfo = null;
        for (Map.Entry<Integer, EnterNameActivityConfig> configEntry : activityConfigMap.entrySet()) {
            EnterNameActivityConfig temp = configEntry.getValue();
            if(config.getActivityInfo().getType() == temp.getActivityInfo().getType()
            && config.getActivityInfo().getChildType() == temp.getActivityInfo().getChildType() && activityId != temp.activityInfo.getActivityId()){
                activityInfo = temp.getActivityInfo();
            }
        }
        if(activityInfo != null){
            activityConfigMap.remove(activityInfo.getActivityId());
            getLogger().info("enter name remove overtime activity {}",activityInfo.getActivityId());
        }
        activityConfigMap.put(activityId, config);
    }

    public static void removeConfig(int activityType){
        List<Integer> list = new ArrayList<>(activityConfigMap.keySet());
        for (Integer key : list) {
            EnterNameActivityConfig activityConfig = activityConfigMap.get(key);
            if(activityConfig != null){
                if(activityConfig.getActivityInfo().getType() == activityType){
                    activityConfigMap.remove(key);
                }
            }
        }
    }

    public static Map<Integer, EnterNameActivityConfig> getActivityConfigMap() {
        return activityConfigMap;
    }

    public static List<EnterNameActivityConfig> getAllInTimeConfig(){
        List<EnterNameActivityConfig> configList = new ArrayList<>();
        for (Map.Entry<Integer, EnterNameActivityConfig> configEntry : activityConfigMap.entrySet()) {
            if(ActivityMgr.activityInShowTime(configEntry.getValue().getActivityInfo())){
                configList.add(configEntry.getValue());
            }
        }
        return configList;
    }

    public static EnterNameProto.ChannelEnterNameUserKeyMsg.Builder buildKeyMsg(long userId){
        EnterNameProto.ChannelEnterNameUserKeyMsg.Builder keyMsg = EnterNameProto.ChannelEnterNameUserKeyMsg.newBuilder();
        keyMsg.setUserId(userId);
        keyMsg.setServerId(GameServer.getInstance().getServerId());
        keyMsg.setChannelId(ServerListMgr.getChannelId(keyMsg.getServerId()));
        return keyMsg;
    }

    public static void cacheEnterName(int activityId, Map<Long, EnterNameCache> cacheMap){
        Map<Long, EnterNameCache> map = nameCacheMap.get(activityId);
        if(map == null){
            synchronized (nameCacheMap){
                map = nameCacheMap.get(activityId);
                if(map == null){
                    map = new ConcurrentHashMap<>();
                    nameCacheMap.put(activityId, map);
                }
            }
        }
        map.putAll(cacheMap);
    }

    public static EnterNameCache getEnterNameCache(int activityId, long userId){
        Map<Long, EnterNameCache> cache = nameCacheMap.get(activityId);
        if(cache == null) {
            return null;
        }
        return cache.get(userId);
    }

    public static boolean handleMedal(GamePlayer player, int goodsId, long longValue) {
        boolean accept = false;
        try {
            for (Map.Entry<Integer, EnterNameActivityConfig> configEntry : activityConfigMap.entrySet()) {
                EnterNameActivityConfig config = configEntry.getValue();
                if(config.getMedalId() == goodsId){
                    accept = true;
                    if(ActivityMgr.activityInTime(config.getActivityInfo())){
                        player.notifyListener(eGamePlayerEventType.EnterNameAreaFightRank.getValue(), new ValueFourParamArgs(BigInteger.valueOf(longValue), config.getActivityInfo().getActivityId()));
                    }
                    break;
                }
            }
        }catch (Exception e){
            getLogger().error("handleMedal error", e);
        }
        return accept;
    }

    public static void autoEnterName() {

        for (Map.Entry<Integer, EnterNameActivityConfig> configEntry : activityConfigMap.entrySet()) {
            EnterNameActivityConfig config = configEntry.getValue();
            if(!ActivityMgr.activityInShowTime(config.getActivityInfo())){
                continue;
            }
            ActivityInfo activityInfo = config.getActivityInfo();
            eActivityToSystem activityToSystem = null;
            for (eActivityToSystem value : eActivityToSystem.values()) {
                if(value.getActivityType() == activityInfo.getType()){
                    activityToSystem = value;
                }
            }

            if(activityToSystem == null){
                getLogger().info("activityId {} type {} not system id", activityInfo.getActivityId(), activityInfo.getType());
                continue;
            }
//            if(!EnterNameActivityMgr.isActivitySystemOpen(player, config.getActivityInfo()))
            List<Integer> limitList = StringUtils.stringToIntegerList(config.getSIGN_UP_LIMIT(), "\\|");
            if(limitList.isEmpty()){
                getLogger().info("activityId {} type {} limit empty", activityInfo.getActivityId(), activityInfo.getType());
                continue;
            }

            if(inAutoEnterNameTime(activityInfo.getActivityId())){

                getLogger().info("activityId {} type {} auto enter name start", activityInfo.getActivityId(), activityInfo.getType());

                List<UserInfo> list = UserMgr.getUserInfoList();
                Iterator<UserInfo> iterator = list.iterator();
                while (iterator.hasNext()){
                    UserInfo userInfo = iterator.next();

                    //活动开始3天内有登录过的
                    if(userInfo.getLastLoginTime() < activityInfo.getBeginTime() - limitList.get(1) * DateHelper.DAY_SECONDS){
                        iterator.remove();
                        continue;
                    }

                    if(userInfo.getTitleId() < limitList.get(0)){
                        iterator.remove();
                        continue;
                    }

                    //报过名的
                    EnterNameCache cache = EnterNameActivityMgr.getEnterNameCache(activityInfo.getActivityId(), userInfo.getUserId());
                    if(cache != null){
                        iterator.remove();
                        continue;
                    }

                    //是否解锁系统的
                    if(!SystemOpenMgr.offlineSystemOpen(userInfo.getSystemOpenValue(), activityToSystem.getSystemId())){
                        iterator.remove();
                        continue;
                    }
                }

                if(list.size() > 0){

                    Random random = new Random();
                    List<Integer> zoneList = new ArrayList<>();
                    for (ChannelFightZone fightZone : config.getFightZoneList()) {
                        zoneList.add(fightZone.getAreaId());
                    }
                    if(zoneList.size() == 0){
                        getLogger().info("enter name activity {} no zone config", activityInfo.getActivityId());
                        continue;
                    }

                    EnterNameProto.ChannelEnterNameAutoAddReqMsg.Builder reqMsg = EnterNameProto.ChannelEnterNameAutoAddReqMsg.newBuilder();
                    reqMsg.setActivityId(activityInfo.getActivityId());
                    reqMsg.setServerId(GameServer.getInstance().getServerId());
                    reqMsg.setChannelId(ServerListMgr.getChannelId(reqMsg.getServerId()));

                    for (UserInfo userInfo : list) {
                        EnterNameProto.ChannelEnterNameAddMsg.Builder builder = EnterNameProto.ChannelEnterNameAddMsg.newBuilder();
                        builder.setUserId(userInfo.getUserId());
                        int zoneId = 0;
                        if(StringUtils.isNullOrEmpty(userInfo.getIpLocation())){
                            //定时器执行，直接调用http
                            //todo

                        }else {
                            int areaCode = EnterNameUtils.getAreaCodeByName(userInfo.getIpLocation());
                            zoneId = config.getAreaIdByMemberCode(areaCode, random);
                        }

                        if(zoneId == 0){
                            int areaCode = EnterNameUtils.getAreaCodeByName(userInfo.getIpLocation());
                            zoneId = config.getAreaIdByMemberCode(areaCode, random);
                        }
                        builder.setZoneId(zoneId);
                        builder.setUserBaseInfo(PlayerPb.parsePlayerBaseTempMsg(userInfo));
                        getLogger().info("enter name activity {} user {} zone {}", activityInfo.getActivityId(), builder.getUserId(), builder.getZoneId());
                        reqMsg.addUser(builder);
                    }
                    getLogger().info("activityId {} type {} auto enter name end , size {}", activityInfo.getActivityId(), activityInfo.getType(), reqMsg.getUserCount());
                    GamePlayerMgr.sendChannelPacket(Protocol.N_ENTER_NAME_ADD_AUTO, reqMsg, 0);
                }
            }
        }

    }

    public static void autoEnterName(int activityId, long userId) {
        EnterNameActivityConfig config = activityConfigMap.get(activityId);
        if(config != null && ActivityMgr.activityInShowTime(config.getActivityInfo())){
            UserInfo userInfo = UserMgr.getUserInfo(userId);
            if(userInfo == null || userInfo.getTitleId() < 15){
                return;
            }
            if(inAutoEnterNameTime(activityId)){

                EnterNameProto.ChannelEnterNameAutoAddReqMsg.Builder reqMsg = EnterNameProto.ChannelEnterNameAutoAddReqMsg.newBuilder();
                reqMsg.setActivityId(activityId);
                reqMsg.setServerId(GameServer.getInstance().getServerId());
                reqMsg.setChannelId(ServerListMgr.getChannelId(reqMsg.getServerId()));

                EnterNameProto.ChannelEnterNameAddMsg.Builder builder = EnterNameProto.ChannelEnterNameAddMsg.newBuilder();
                builder.setUserId(userId);
                //随机一个区域
                Random random = new Random();
                List<Integer> zoneList = new ArrayList<>();
                for (ChannelFightZone fightZone : config.getFightZoneList()) {
                    zoneList.add(fightZone.getAreaId());
                }
                if(zoneList.size() == 0){
                    getLogger().info("enter name activity {} no zone config", activityId);
                    return;
                }
                builder.setZoneId(zoneList.get(random.nextInt(zoneList.size())));
                builder.setUserBaseInfo(PlayerPb.parsePlayerBaseTempMsg(userInfo));
                reqMsg.addUser(builder);
                GamePlayerMgr.sendChannelPacket(Protocol.N_ENTER_NAME_ADD_AUTO, reqMsg, 0);
                getLogger().info("enter name user {} auto enter name activity {}", userId, activityId);
            }
        }
    }

    public static EnterNameProto.ChannelEnterNameGetRankForRewardReqMsg.Builder builderRewardRankGet(long userId, int activityId, int conditionId, int conditionType){
        EnterNameProto.ChannelEnterNameGetRankForRewardReqMsg.Builder builder = EnterNameProto.ChannelEnterNameGetRankForRewardReqMsg.newBuilder();
        builder.setActivityId(activityId);
        builder.setType(conditionType);
        builder.setConditionId(conditionId);
        builder.setUserKey(buildKeyMsg(userId));
        return builder;
    }

    public static boolean isActivitySystemOpen(GamePlayer player, ActivityInfo activityInfo){
        eActivityToSystem temp = null;
        for (eActivityToSystem activityToSystem : eActivityToSystem.values()) {
            if(activityToSystem.getActivityType() == activityInfo.getType()){
                temp = activityToSystem;
            }
        }
        if(temp == null){
            return false;
        }
        return SystemOpenMgr.systemOpen(player, temp.getSystemId());
    }

    public static void checkEnterNameCache() {
        for (Map.Entry<Integer, EnterNameActivityConfig> entry : activityConfigMap.entrySet()) {
            int activityId = entry.getKey();
            if(nameCacheMap.containsKey(activityId)){
                continue;
            }
            //尝试上跨服拉缓存
            EnterNameProto.Cross3EnterNameAllSyncReqMsg.Builder reqMsg = EnterNameProto.Cross3EnterNameAllSyncReqMsg.newBuilder();
            reqMsg.setActivityId(activityId);
            GamePlayerMgr.sendPacket(0, YanQuMessageUtils.buildMessage(Protocol.C3_ENTER_NAME_ALL_NAME_SYNC_TO_SEVER, reqMsg));
        }
    }

    public static Map<Integer, List<ActivityGroupMatch>> getMatchMap() {
        return matchMap;
    }

    public static void setMatchMap(Map<Integer, List<ActivityGroupMatch>> matchMap) {
        EnterNameActivityMgr.matchMap = matchMap;
    }

    public static int getGroupId(int activityId, int zoneId){
        List<ActivityGroupMatch> list = matchMap.get(activityId);
        if(list != null){
            for (ActivityGroupMatch groupMatch : list) {
                if(groupMatch.getZoneIdList().contains(zoneId)){
                    return groupMatch.getGroupId();
                }
            }
        }
        return 0;
    }
}
